package com.chuhe.starry.service.impl;

import com.chuhe.common.constans.MyConstants;
import com.chuhe.common.domain.dto.MessageSendDto;
import com.chuhe.common.domain.dto.TokenUserInfoDto;
import com.chuhe.common.domain.entity.*;
import com.chuhe.common.domain.enums.*;
import com.chuhe.common.domain.query.PaginationResultVO;
import com.chuhe.common.domain.query.SimplePage;
import com.chuhe.common.domain.query.UserContactQuery;
import com.chuhe.common.domain.vo.req.AdminLoadGroupReq;
import com.chuhe.common.domain.vo.resp.*;
import com.chuhe.common.exception.BusinessException;
import com.chuhe.common.exception.CommonErrorEnum;
import com.chuhe.common.utils.*;
import com.chuhe.starry.dao.*;
import com.chuhe.starry.mapper.ChatMessageMapper;
import com.chuhe.starry.mapper.ChatSessionUserMapper;
import com.chuhe.starry.service.ChatSessionUserService;
import com.chuhe.starry.service.GroupInfoService;
import com.chuhe.starry.service.UserContactService;
import com.chuhe.starry.service.UserInfoService;
import com.chuhe.starry.service.adapter.LoadOnGroupContactAdapter;
import com.chuhe.starry.service.adapter.SaveGroupAdapter;
import com.chuhe.starry.websocket.ChannelContextUtils;
import com.chuhe.starry.websocket.MessageHandler;
import com.sun.corba.se.pept.transport.ContactInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.Date;

/**
 * @Author: 楚河
 * @Date: 2025年05月12日20:57
 */
@Service
@Slf4j
public class GroupInfoServiceImpl implements GroupInfoService {
    public static final int MEMBER_COUNT_1 = 1;
    @Autowired
    private GroupInfoDao groupInfoDao;
    @Autowired
    private RedisComponet redisComponet;
    @Autowired
    private UserContactDao userContactDao;
    @Autowired
    private AppConfig appConfig;
    @Autowired
    private ChatSessionDao chatSessionDao;
    @Autowired
    private ChatMessageMapper chatMessageMapper;
    @Autowired
    private ChatSessionUserMapper chatSessionUserMapper;
    @Autowired
    private ChatSessionUserDao chatSessionUserDao;
    @Autowired
    private ChannelContextUtils channelContextUtils;
    @Autowired
    private ChatMessageDao chatMessageDao;
    @Autowired
    private MessageHandler messageHandler;
    @Autowired
    private ChatSessionUserService chatSessionUserService;
    @Lazy
    @Autowired
    private GroupInfoService groupInfoService;
    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserContactService userContactService;

    /**
     * 创建群组
     * @Author: 楚河
     * @Date: 2025-05-13 18:17
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<?> saveGroup(SaveGroupReq req, TokenUserInfoDto tokenUserInfo) {
        //装填入参 准备入库
        GroupInfo groupInfo = SaveGroupAdapter.buildGroup(req,tokenUserInfo);
        //新增？
        if(Objects.isNull(groupInfo.getGroupId())){
            groupInfo.setGroupId(StringTools.getGroupId());
            //查询数量，超过限制则不可创建
            Integer count = groupInfoDao.selectCount(groupInfo.getGroupOwnerId());
            SysSettingResp sysSetting = redisComponet.getSysSetting();
            AssertUtil.isTrue(count >= sysSetting.getMaxGroupCount(),"最多支持创建" + sysSetting.getMaxGroupCount() + "个群聊");
            //图片未传抛出异常
            AssertUtil.isTrue(Objects.isNull(req.getAvatarFile()), CommonErrorEnum.CODE_600);
            //群聊数据入库
            groupInfoDao.save(groupInfo);
            //将群组添加为联系人 数据入库
            UserContact userContact = SaveGroupAdapter.buildGroupToUserContact(groupInfo);
            userContactDao.save(userContact);

            Date curDate = new Date();
            // 创建会话
            String sessionId = StringTools.getChatSessionId4Group(groupInfo.getGroupId());
            ChatSession chatSession = new ChatSession();
            chatSession.setSessionId(sessionId);
            chatSession.setLastMessage(MessageTypeEnum.GROUP_CREATE.getInitMessage());
            chatSession.setLastReceiveTime(curDate.getTime());
            chatSessionDao.save(chatSession);

            //创建群组会话
            ChatSessionUser chatSessionUser = new ChatSessionUser();
            chatSessionUser.setUserId(groupInfo.getGroupOwnerId());
            chatSessionUser.setContactId(groupInfo.getGroupId());
            chatSessionUser.setContactName(groupInfo.getGroupName());
            chatSessionUser.setSessionId(sessionId);
            chatSessionUserDao.save(chatSessionUser);

            //添加为联系人
            redisComponet.addUserContact(groupInfo.getGroupOwnerId(),groupInfo.getGroupId());
            channelContextUtils.addUser2Group(groupInfo.getGroupOwnerId(),groupInfo.getGroupId());

            //创建消息
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSessionId(sessionId);
            chatMessage.setMessageType(MessageTypeEnum.GROUP_CREATE.getType());
            chatMessage.setMessageContent(MessageTypeEnum.GROUP_CREATE.getInitMessage());
            chatMessage.setSendUserId(null);
            chatMessage.setSendUserNickName(null);
            chatMessage.setSendTime(curDate.getTime());
            chatMessage.setContactId(groupInfo.getGroupId());
            chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
            chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
            chatMessageMapper.insert(chatMessage);
            //发送WS消息
            chatSessionUser.setLastMessage(MessageTypeEnum.GROUP_CREATE.getInitMessage());
            chatSessionUser.setLastReceiveTime(curDate.getTime());
            chatSessionUser.setMemberCount(1);
            chatSessionUser.setContactType(UserContactTypeEnum.GROUP.getType());

            MessageSendDto messageSend = CopyTools.copy(chatMessage, MessageSendDto.class);
            messageSend.setExtendData(chatSessionUser);
            messageSend.setLastMessage(chatSessionUser.getLastMessage());
            messageHandler.sendMessage(messageSend);
        }else {//修改
            //检查被修改的是否是当前群组
            GroupInfo editGroupInfo = groupInfoDao.selectByGroupId(req.getGroupId());
            AssertUtil.isEmpty(editGroupInfo,CommonErrorEnum.CODE_600);
            //修改入库
            groupInfoDao.updateGroup(groupInfo);

            //更新相关表冗余的字段
            String contactNameUpdate = null;
            if (!editGroupInfo.getGroupName().equals(groupInfo.getGroupName())) {
                contactNameUpdate = groupInfo.getGroupName();
            }
            //修改群昵称发送ws消息
            chatSessionUserService.updateRedundanceInfo(contactNameUpdate, groupInfo.getGroupId());
        }
        //群头像处理
        if(Objects.isNull(req.getAvatarFile())){
            return null;
        }
        String baseFolder = appConfig.getProjectFolder() + MyConstants.FILE_FOLDER_FILE;
        File targetFileFolder = new File(baseFolder + MyConstants.FILE_FOLDER_AVATAR_NAME);
        if(!targetFileFolder.exists()){
            targetFileFolder.mkdirs();
        }
        String filePath = targetFileFolder.getPath() + File.separator + groupInfo.getGroupId();
        try {
            req.getAvatarFile().transferTo(new File(filePath + MyConstants.IMAGE_SUFFIX));
            req.getAvatarCover().transferTo(new File(filePath + MyConstants.COVER_IMAGE_SUFFIX));
        }catch (Exception e){
            throw new BusinessException("头像上传失败");
        }
        return null;
    }

    /**
     * 获取群组
     * @Author: 楚河
     * @Date: 2025-05-14 16:10
     */
    @Override
    public List<LoadGroupResp> loadMyGroup(String userId) {
        return groupInfoDao.selectGroupList(userId);
    }

    /**
     * 获取群组详情
     * @Author: 楚河
     * @Date: 2025-05-14 19:16
     */
    @Override
    public LoadGroupResp getGroupDetail(String userId, String groupId) {
        //获取群聊信息
        GroupInfo groupInfo = getGroupInfo(userId, groupId);
        //查询在群联系人数量
        Integer cont = userContactDao.getOnGroupUserCount(groupId);
        //组装返回
        return SaveGroupAdapter.buildGroupDetail(groupInfo,cont);
    }
    //获取群聊信息
    public GroupInfo getGroupInfo(String userId, String groupId){
        //校验参数
        UserContact userContact = userContactDao.getUserContactByUserId(userId,groupId);
        if(userContact == null || !UserContactStatusEnum.FRIEND.getStatus().equals(userContact.getStatus())){
            throw new BusinessException("你不在群聊或者群聊不存在或者已经解散了");
        }
        //查询群聊
        GroupInfo groupInfo = groupInfoDao.getGroupByGroupid(groupId);
        if(groupInfo == null || !GroupStatusEnum.NORMAL.getStatus().equals(groupInfo.getJoinType())){
            throw new BusinessException("群聊不存在或者已经解散");
        }
        return groupInfo;
    }

    /**
     * 加载群组会话联系人
     * @Author: 楚河
     * @Date: 2025-05-14 20:04
     */
    @Override
    public LoadGroupSessionResp getGroupInfo4Chat(String userId, String groupId) {
        //获取群聊信息
        GroupInfo groupInfo = getGroupInfo(userId, groupId);
        //查询会话联系人
        UserContact userContact = LoadOnGroupContactAdapter.buildOnGroupContact(groupInfo,groupId);
        List<UserContactVo> userContactList = userContactDao.getOnGroupUserContact(userContact.getContactId());
        //组装返回
        return LoadOnGroupContactAdapter.buildUserContactList(groupInfo,userContactList);
    }

    /**
     * 查询所有群组 分页
     * @Author: 楚河
     * @Date: 2025-05-18 14:14
     */
    @Override
    public PaginationResultVO<GroupInfo> findListByPage(AdminLoadGroupReq req) {
        int count = groupInfoDao.selectGroupCount();
        int pageSize = req.getPageSize() == null ? PageSize.SIZE15.getSize() : req.getPageSize();

        SimplePage page = new SimplePage(req.getPageNo(),count,pageSize);
        req.setSimplePage(page);
        List<GroupInfo> list = groupInfoDao.selectAllGroup(req);
        PaginationResultVO<GroupInfo> resultVO = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return resultVO;
    }

    /**
     * 解散群组
     * @Author: 楚河
     * @Date: 2025-05-18 14:29
     */
    @Override
    public void dissolutionGroup(String userId, String groupId) {
        //查询该群组
        GroupInfo groupInfo = groupInfoDao.selectByGroupId(groupId);
        AssertUtil.isEmpty(groupInfo,CommonErrorEnum.CODE_600);
        //删除群组 （逻辑删）
        groupInfoDao.delGroupByGroupId(groupId);
        //删除联系人（逻辑删，改变状态）
        userContactDao.delGroup(groupId);
        //刷新缓存
        List<UserContact> userContactList = userContactDao.selectGroupContactList(groupId, UserContactTypeEnum.GROUP.getType());
        for (UserContact userContact : userContactList) {
            redisComponet.removeuserContact(userContact.getUserId(),userContact.getContactId());
        }

        //todo 退群会话消息
        String sessionId = StringTools.getChatSessionId4Group(groupId);
        Date curTime = new Date();
        String messageContent = MessageTypeEnum.DISSOLUTION_GROUP.getInitMessage();
        //更新会话消息
        ChatSession chatSession = new ChatSession();
        chatSession.setLastMessage(messageContent);
        chatSession.setLastReceiveTime(curTime.getTime());
        chatSessionDao.updateBySessionId(chatSession,sessionId);
        //记录消息消息表
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setSessionId(sessionId);
        chatMessage.setSendTime(curTime.getTime());
        chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
        chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
        chatMessage.setMessageType(MessageTypeEnum.DISSOLUTION_GROUP.getType());
        chatMessage.setContactId(groupId);
        chatMessage.setMessageContent(messageContent);
        chatMessageMapper.insert(chatMessage);
        //发送解散群消息
        MessageSendDto messageSendDto = CopyTools.copy(chatMessage, MessageSendDto.class);
        messageHandler.sendMessage(messageSendDto);
    }

    /**
     * 拉人或踢人
     * @Author: 楚河
     * @Date: 2025-05-24 17:22
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrRemoveGroupUser(TokenUserInfoDto tokenUserInfoDto, String groupId, String contactIds, Integer opType) {
        GroupInfo groupInfo = groupInfoDao.selectByGroupId(groupId);
        if (null == groupInfo || !groupInfo.getGroupOwnerId().equals(tokenUserInfoDto.getUserId())) {
            throw new BusinessException(CommonErrorEnum.CODE_600);
        }
        String[] contactIdList = contactIds.split(",");
        for (String contactId : contactIdList) {
            //移除群员
            if (MyConstants.ZERO.equals(opType)) {
                groupInfoService.leaveGroup(contactId, groupId, MessageTypeEnum.REMOVE_GROUP);
            } else {
                userContactService.addUserContact(contactId,groupId , null, null,UserContactTypeEnum.GROUP.getType());
            }
        }
    }

    /**
     * 移除
     * @Author: 楚河
     * @Date: 2025-05-24 17:24
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void leaveGroup(String userId, String groupId, MessageTypeEnum messageTypeEnum) {
        GroupInfo groupInfo = groupInfoDao.selectByGroupId(groupId);
        if (groupInfo == null) {
            throw new BusinessException(CommonErrorEnum.CODE_600);
        }
        //创建者不能退出群聊，只能解散群
        if (userId.equals(groupInfo.getGroupOwnerId())) {
            throw new BusinessException(CommonErrorEnum.CODE_600);
        }
        Boolean group  = userContactDao.deleteByUserIdAndContactId(userId, groupId);
        if (!group) {
            throw new BusinessException(CommonErrorEnum.CODE_600);
        }

        UserInfo userInfo = userInfoDao.selectByUserId(userId);

        String sessionId = StringTools.getChatSessionId4Group(groupId);
        Date curTime = new Date();
        String messageContent = String.format(messageTypeEnum.getInitMessage(), userInfo.getNickName());
        //更新会话消息
        ChatSession chatSession = new ChatSession();
        chatSession.setLastMessage(messageContent);
        chatSession.setLastReceiveTime(curTime.getTime());
        chatSessionDao.updateBySessionId(chatSession, sessionId);
        //记录消息消息表
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setSessionId(sessionId);
        chatMessage.setSendTime(curTime.getTime());
        chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
        chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
        chatMessage.setMessageType(messageTypeEnum.getType());
        chatMessage.setContactId(groupId);
        chatMessage.setMessageContent(messageContent);
        chatMessageMapper.insert(chatMessage);

        UserContactQuery userContactQuery = new UserContactQuery();
        userContactQuery.setContactId(groupId);
        userContactQuery.setStatus(UserContactStatusEnum.FRIEND.getStatus());
        Integer memberCount = userContactDao.selectCountById(userContactQuery);

        MessageSendDto messageSendDto = CopyTools.copy(chatMessage, MessageSendDto.class);
        messageSendDto.setExtendData(userId);
        messageSendDto.setMemberCount(memberCount);
        messageHandler.sendMessage(messageSendDto);
    }

}
